import 'dart:async';
import 'dart:convert';

import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/status.dart' as status;

import '../../common/base_config.dart';

/// WebSocket状态
enum SocketStatus {
  connected, // 连接
  failed, // 失败
  closed, // 关闭
}


class MyWebSocket {

  // 存储websocket侦听对象
  IOWebSocketChannel _webSocket;

  // webSocket状态
  SocketStatus _socketStatus;

  // websocket连接地址（地址前缀）
  String _URL;

  // 心跳定时器
  Timer _heartBeat;

  // 心跳间隔(秒)
  num _heartTimes = 3;

  // 回调函数
  Function onMessage; // 成功接受的回调
  Function onError; // 错误信息的回调
  Function onDone;// 关闭侦听的回调

  /// ### 初始化websocket
  /// #### [url] String|必填|连接地址（不含浅醉）
  /// #### [onMessage] Function|选填|成功接受的回调
  /// #### [onError] Function|选填|错误信息的回调
  /// #### [Done] Function|选填|关闭侦听的回调
  MyWebSocket(String url,{ Function onMessage, Function onError, Function onDone }) {
    // 拼接完成连接地址
    _URL = "${BaseConfig.BASE_WS + url}";

    // 存储回调函数
    this.onMessage = onMessage;
    this.onError = onError;
    this.onDone = onDone;

    // 执行openSocket函数
    openSocket();
  }


  /// ### 打开websocket
  /// #### 函数创建与服务端的通讯，并能侦听每一次服务端的数据响应
  openSocket() {
    // 1、关闭已存在的webSokcet，防止多次被开启
    closeSocket();

    // 2、创建与服务端的连接（注：此时不一定已经连接成功，相关回调信息需要在listen函数中查看）
    _webSocket = new IOWebSocketChannel.connect(_URL);

    // 4、标记webSokcet连接成功（此处为“假定”状态，真实状态需要在listen函数中查看）
    _socketStatus = SocketStatus.connected;

    // 3、创建“心跳机制”，以保证WebSocket的鲜活性
    _initHeartBeat();

    // 5、实行webSokcet侦听
    _webSocket.stream.listen(
      (data) {
        /**
          // 注：此处的“pong”是与服务端已达成的约定。为保证websokcet鲜活性而建立的
          if(data == "pong") {
            print("$data");
          } else {
            onMessage(data);
          }
        */
        if(data != "pong") {
          onMessage(json.decode(data));
        } else {
          //print("$data");
          onMessage(data);
        }
      },
      onError: (error){
        closeSocket();
        // 标记webSokcet发生错误（此处状态为真实状态）
        _socketStatus = SocketStatus.failed;
        onError(error);
      },
      onDone: () {
        closeSocket();
        // 标记webSokcet已经关闭（此处状态为真实状态）
        _socketStatus = SocketStatus.closed;
        onDone();
      },
    );
  }


  /// ### 关闭webSocket
  closeSocket() async {
    if (_webSocket != null) {

      // 关闭webSocket
      //_webSocket.sink.close();

      await _webSocket.sink.close(status.goingAway);

      // 销毁心跳
      _destroyHeartBeat();

      // 标记websokcet状态
      _socketStatus = SocketStatus.closed;

      //print("调了关闭函数");

    }
  }

  /// ### 初始化心跳机制
  _initHeartBeat() {
    _heartBeat = Timer.periodic(Duration(seconds: _heartTimes), (t) {
      _sendMessage("ping");
    });
  }

  /// ### 销毁心跳
  void _destroyHeartBeat() {
    if (_heartBeat != null) {
      _heartBeat.cancel();
      _heartBeat = null;
    }
  }

  /// ### 向服务器发送数据
  /// #### [message] String|必填|发送的内容
  void _sendMessage(String message) {
    if (_webSocket != null) {
      switch (_socketStatus) {
        case SocketStatus.connected:
          _webSocket.sink.add(message);
          break;
      }
    }
  }


}